//The MIT License
//
//Copyright (c) 2009 nodchip
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in
//all copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//THE SOFTWARE.
package tv.dyndns.kishibe.client.creation;

import java.util.ArrayList;
import java.util.List;

import tv.dyndns.kishibe.client.Constant;
import tv.dyndns.kishibe.client.Sanitize;
import tv.dyndns.kishibe.client.Service;
import tv.dyndns.kishibe.client.UserData;
import tv.dyndns.kishibe.client.Utility;
import tv.dyndns.kishibe.client.packet.PacketProblemData;

import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

public class WidgetProblemForm extends VerticalPanel implements ClickHandler, ChangeHandler {
	private static final String[] TYPE_CAUTION = { "",//
			"「○」と「×」の二者択一による問題です<br/>解答欄には「○」又は「×」、画像問題の場合は画像URLを入力してください<br/>「o」「x」ではありません<br/>「～である」や「～だった」あるいはそれに類する文末にしてくだい",//
			"その名の通り4つの選択肢による四者択一問題です<br/>4つの解答欄の一番上に正答、それ以外にダミー解答を入力してください<br/>画像問題の場合は画像URLを入力してください<br/>分岐可能です<br/>文末は「～は？」などのように言い切りで疑問符をつけるようにしてください<br/>１枚の静止画あるいは動画を併用できます",//
			"４つの項目(ヒント)を時間をずらして表示する方法による四者択一問題です<br/>4つの解答欄の一番上に正答、それ以外にダミー解答を入力してください<br/>画像問題の場合は画像URLを入力してください<br/>分岐可能です<br/>問題の入力は各行に1つのフレーズを入力してください<br/>1行に1つずつ、合計4つの項目を記してください<br/>1、2、3行目の末尾には必ずウェイトを入れてください<br/>3行目のウェイトは1、2行目よりも多くしてください",//
			"ランダムに入れ替わった単語や文章を正しく並べ替えて解答させる問題です<br/>解答欄に解答を入力してください<br />含まれる文字が同じ場合は複数の解答を正解とさせることができます<br/>原則9文字までとします<br/>文末は「～は？」などのように言い切りで疑問符をつけるようにしてください",//
			"6又は10種類の文字から文字を選択して3～6文字の言葉を完成させ解答させる問題です<br/>解答欄に解答、選択肢に画面に表示する6又は10文字を入力して下さい<br/>分岐可能です<br/>文末は「～は？」などのように言い切りで疑問符をつけるようにしてください<br/>伏せ字(○)を使った形式では、タイピングクイズで用いられている「○を答えなさい」というような脚注は不要です<br/>1枚の静止画を併用できます",//
			"画面上に表示される「ひらがな」「カタカナ」「英数字(英字は大文字のみ)」のいずれか1つのキーボードを使って解答を直接入力させる問題です<br/>解答欄に解答を入力してください<br/>解答は「ひらがな」「カタカナ」「英数字」のみとし、混在しないようにしてください<br/>揺らぎ解答がある場合は解答欄の上から順に記入してください<br/>分岐可能です<br/>最も基本とされるのは伏せ字（○）を用い、脚注をつける形式です<br/>※例<br/>・伏字部分が漢字の場合はひらがなで答えさせる場合<br/>　日本の首都は○○？○の漢字をひらがなで答えなさい<br/>　2005年現在の日本の内閣総理大臣は小泉○○○？○の名前をひらがなで答えなさい<br/>　覚醒剤所持の容疑で逮捕された元ラッツ＆スターのメンバーは○○まさし？○の苗字をひらがなで答えなさい<br/>・伏字部分に漢字とひらがなが混在している場合は文字数を指定してひらがなで答えさる場合<br/>　ザ・ドリフターズのメンバーで最年少なのは○○○○？○をひらがな５文字で答えなさい<br/>・伏字部分に漢字が含まれていない場合はそのまま答えさせる<br/>　長谷川町子原作の国民的アニメのタイトルは『○○○さん』○を答えなさい<br/>上記の形式以外にも、○による伏せ字を使わずに「カタカナ２文字で答えなさい」<br/>「数字で答えなさい」という脚注をつけるという方法での出題も可能です<br/>いずれの場合も問題本文の文末は疑問符にし、脚注文末に句読点をつける必要はありません<br/>なお、１枚の静止画あるいは動画を併用できます",//
			"画面に部分的に表示される文字を並び替えて、タイピングクイズと同様のキーボードを用い、解答を直接入力させる問題です<br/>本家のキューブクイズ互換です<br/>解答欄に解答、選択肢に画面の表示するヒントを入力してください<br/>解答は「ひらがな」「カタカナ」「英数字」のみとし、混在しないようにしてください<br />含まれる文字が同じ場合は複数の解答を正解とさせることができます<br/>文末は体言止めや「です・ます調」にするか、「～は？」などのように言い切りで疑問符をつけてください<br >画像は併用できません",//
			"問題文とともに、ヒントとなる文字あるいは画像をエフェクトをかけて表示し、タイピングクイズと同様のキーボードを用い、解答を直接入力させる問題です<br/>解答欄に解答を入力してください<br/>解答は「ひらがな」「カタカナ」「英数字」のみとし、混在しないようにしてください<br/>文末は体言止めや「です・ます調」にするか、「～は？」などのように言い切りで疑問符をつけてください",//
			"4つの選択肢を用意し、問題文で指定した該当項目を全て選ばせる問題です<br/>選択肢に4つの選択肢、解答欄に解答を入力してください<br/>画像問題の場合は画像URLを入力してください<br/>問題文は「次のうち～を全て選びなさい」「次の***のうち～を全て選びなさい」という形にしてください<br/>QMACloneでは選択肢は4つまでとなります<br/>分岐は不可能です",//
			"3つあるいは4つの選択肢を用意し、問題文で指定した順番通りに選ばせる問題です<br/>解答欄に上から順に問題の答えを入力してください<br/>画像問題の場合は画像URLを入力してください<br/>問題文は「次の**を（**が）大きい順or小さい順etc.に選びなさい」(序列)<br/>「次の**を順番に選んで***に(なるように)しなさい」(序列・アナグラム)<br/>「次の文字列or画像を順番に選んで***に(なるように)しなさい」(アナグラム)<br/>といった形になるようにしてください<br/>分岐は不可能です",//
			"3組又は4組の正しい組み合わせを答えさせる問題です<br/>解答欄と選択肢にそれぞれ対応する答えを順に書いてください<br/>画像問題の場合は画像URLを入力してください<br/>問題文は「次の○○と○○の正しい組み合わせを選びなさい」「次の文字列を組み合わせて○○の名前にしなさい」「次の○○と○○を組み合わせて○○の名前にしなさい」という形にしてください<br/>分岐は不可能です",//
			"各縦列から正しい文字を選び答えさせる問題です<br/>4つの解答欄の一番上に正答、それ以外にダミー解答を入力してください<br/>文末は「～は？」などのように言い切りで疑問符をつけるようにしてください<br/>分岐可能です",//
			"画像中の正解となる領域をクリックして答えさせる問題です<br/>選択肢の一番上に画像URLを入力してください<br/>正解となる領域を入力するには解答欄の右側のボタンを押して表示されるインタフェースを使ってください<br/>領域は最大で4つまで指定できます",//
			"マウスで文字を描いて入力させる問題です<br/>解答欄に解答を入力してください<br/>複数解答可能です<br/>使用可能な文字に注意してください<br/>投稿後に10回程度、実際に候補が現れることを確認してください<br/>\"口(くち)\"と\"□(しかく)\"等、紛らわしい文字は避けてください" };

	// private static final String[][] LIST_BOX_GENRE = { { "ジャンルを選んでください", "0" }, { "アニメ＆ゲーム", "" + Constant.GENRE_ANIGE }, { "スポーツ", "" + Constant.GENRE_SPORTS }, { "芸能", "" + Constant.GENRE_GEINOU }, { "ライフスタイル", "" + Constant.GENRE_LIFESTYLE }, { "社会", "" + Constant.GENRE_SOCIETY }, { "文系学問", "" + Constant.GENRE_HUMANITIES }, { "理系学問", "" + Constant.GENRE_SCIENCE }, };
	private static final String[][] LIST_BOX_GENRE = { { "ジャンルを選んでください", "0" }, { "アニメ＆ゲーム", "" + Constant.GENRE_ANIGE }, { "スポーツ", "" + Constant.GENRE_SPORTS }, { "芸能", "" + Constant.GENRE_GEINOU }, { "雑学", "" + Constant.GENRE_ZATSUGAKU }, { "学問", "" + Constant.GENRE_GAKUMON }, };
	private static final String[][] LIST_BOX_TYPE = { { "出題形式を選んでください", "0" }, { "○×", "" + Constant.TYPE_MARUBATU }, { "四択", "" + Constant.TYPE_4TAKU }, { "連想", "" + Constant.TYPE_RENSOU }, { "並べ替え", "" + Constant.TYPE_NARABEKAE }, { "文字パネル", "" + Constant.TYPE_MOJIPANEL }, { "タイピング", "" + Constant.TYPE_TYPING }, { "フラッシュ", "" + Constant.TYPE_FLASH }, { "エフェクト", "" + Constant.TYPE_EFFECT }, { "一問多答", "" + Constant.TYPE_TATO }, { "順番当て", "" + Constant.TYPE_JUNBAN }, { "線結び", "" + Constant.TYPE_SENMUSUBI }, { "スロット", "" + Constant.TYPE_SLOT }, { "画像クリック", "" + Constant.TYPE_CLICK }, { "手書き", "" + Constant.TYPE_TEGAKI } };
	private static final int TYPE_INPUT_ANSWER[] = { 0, 1, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 };
	private static final int TYPE_INPUT_CHOICE[] = { 0, 2, 4, 4, 0, 1, 0, 0, 1, 4, 0, 4, 0, 1, 0 };
	private static final boolean TYPE_IMAGE_ANSWER[] = { false, false, false, false, false, false, false, false, false, false, true, true, false, false, false };
	private static final boolean TYPE_IMAGE_CHOICE[] = { false, true, true, true, false, false, false, false, false, true, false, true, false, false, false };
	private static final boolean TYPE_POLYGON_CREATION[] = { false, false, false, false, false, false, false, false, false, false, false, false, false, true, false };
	private static final String HALF_FULL_LETTER[] = { "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", "ＡＢＣＤＥＦＧＨＩＪＫＬＭＮＯＰＱＲＳＴＵＶＷＸＹＺ０１２３４５６７８９" };
	private final Label labelProblemNumber = new Label("新規問題を作成中");
	private final ListBox listBoxGenre = new ListBox();
	private final ListBox listBoxType = new ListBox();
	private final ListBox listBoxRandomFlag = new ListBox();
	private final TextArea textAreaSentence = new TextArea();
	private final TextBox[] textBoxAnswer = new TextBox[4];
	private final TextBox[] textBoxChoice = new TextBox[4];
	private final TextBox textBoxCreater = new TextBox();
	private final TextBox textBoxNote = new TextBox();
	private final PanelProblemCreation panelProblemCreation;
	private final Label labelAnswerCounter = new Label("0/0");
	private final Button buttonResetAnswerCount = new Button("リセット", this);
	private final Label labelVoteCounter = new Label("0/0");
	private final Button buttonResetVoteCount = new Button("リセット", this);
	private final CheckBox checkBoxImageChoice = new CheckBox("画像選択肢");
	private final CheckBox checkBoxImageAnswer = new CheckBox("画像回答");
	private final Button buttonRemovePlayerAnswers = new Button("誤回答を削除する", this);
	private int problemId = -1;
	private final List<Button> buttonPolygonCreation = new ArrayList<Button>();
	private final VerticalPanel panelProblemFeedback = new VerticalPanel();
	private final Button buttonClearProblemFeedback = new Button("クリア", this);

	public WidgetProblemForm(PanelProblemCreation panelProblemCreation) {
		this.panelProblemCreation = panelProblemCreation;

		// 問題番号
		add(labelProblemNumber);

		final Grid grid = new Grid(11, 2);
		grid.addStyleName("gridFrame");
		grid.addStyleName("gridFontNormal");

		// ジャンル
		for (int i = 0; i < LIST_BOX_GENRE.length; ++i) {
			getListBoxGenre().addItem(LIST_BOX_GENRE[i][0], LIST_BOX_GENRE[i][1]);
		}
		getListBoxGenre().setWidth("200px");
		grid.setText(0, 0, "ジャンル");
		grid.setWidget(0, 1, getListBoxGenre());

		// 出題形式
		for (int i = 0; i < LIST_BOX_TYPE.length; ++i) {
			getListBoxType().addItem(LIST_BOX_TYPE[i][0], LIST_BOX_TYPE[i][1]);
		}
		getListBoxType().setWidth("200px");
		getListBoxType().addChangeHandler(this);
		grid.setText(1, 0, "出題形式");
		grid.setWidget(1, 1, getListBoxType());

		// ランダムフラグ
		for (int i = 1; i <= 5; ++i) {
			listBoxRandomFlag.addItem("" + i, "" + i);
		}
		listBoxRandomFlag.setSelectedIndex(4);
		listBoxRandomFlag.setWidth("100px");
		grid.setText(2, 0, "ランダムフラグ");
		grid.setWidget(2, 1, listBoxRandomFlag);

		// 問題文
		getTextAreaSentence().setCharacterWidth(60);
		getTextAreaSentence().setVisibleLines(5);
		grid.setText(3, 0, "問題文");
		grid.setWidget(3, 1, getTextAreaSentence());

		// 選択肢
		final VerticalPanel choicePanel = new VerticalPanel();
		for (int i = 0; i < 4; ++i) {
			textBoxChoice[i] = new TextBox();
			textBoxChoice[i].setWidth("400px");
			choicePanel.add(textBoxChoice[i]);
		}
		choicePanel.add(checkBoxImageChoice);
		grid.setText(4, 0, "選択肢");
		grid.setWidget(4, 1, choicePanel);

		// 解答
		final VerticalPanel answerPanel = new VerticalPanel();
		for (int i = 0; i < 4; ++i) {
			final HorizontalPanel panel = new HorizontalPanel();
			panel.setVerticalAlignment(ALIGN_MIDDLE);
			answerPanel.add(panel);

			textBoxAnswer[i] = new TextBox();
			textBoxAnswer[i].setWidth("400px");
			panel.add(textBoxAnswer[i]);

			final Button button = new Button("領域作成", this);
			panel.add(button);
			buttonPolygonCreation.add(button);
		}
		answerPanel.add(checkBoxImageAnswer);
		grid.setText(5, 0, "解答");
		grid.setWidget(5, 1, answerPanel);

		// 作成者
		getTextBoxCreater().setWidth("200px");
		getTextBoxCreater().setMaxLength(6);
		getTextBoxCreater().setText(UserData.getInstance().getPlayerName());
		grid.setText(6, 0, "作成者");
		grid.setWidget(6, 1, getTextBoxCreater());

		// 回答数
		grid.setText(7, 0, "回答数");
		HorizontalPanel panelAnswerCount = new HorizontalPanel();
		panelAnswerCount.add(getLabelAnswerCounter());
		panelAnswerCount.add(buttonResetAnswerCount);
		panelAnswerCount.add(buttonRemovePlayerAnswers);
		buttonRemovePlayerAnswers.setVisible(false);
		grid.setWidget(7, 1, panelAnswerCount);

		// 回答数
		grid.setText(8, 0, "投票数");
		HorizontalPanel panelVoteCount = new HorizontalPanel();
		panelVoteCount.add(labelVoteCounter);
		panelVoteCount.add(buttonResetVoteCount);
		grid.setWidget(8, 1, panelVoteCount);

		// 問題ノート
		grid.setText(9, 0, "問題ノート");
		textBoxNote.setMaxLength(64);
		textBoxNote.setWidth("400px");
		grid.setWidget(9, 1, textBoxNote);

		// 問題評価
		grid.setText(10, 0, "問題評価");
		grid.setWidget(10, 1, panelProblemFeedback);

		add(grid);

		changeAnswerAndChoiceForm();
	}

	public void setProblemData(PacketProblemData problemData, boolean copy) {
		// 問題データを入力フォームに設定する
		// TODO 範囲外の値をセットしようとしたときにJavaとブラウザで挙動が違うのを報告する
		getListBoxGenre().setSelectedIndex(problemData.genre);
		getListBoxType().setSelectedIndex(problemData.type);
		listBoxRandomFlag.setSelectedIndex(problemData.randomFlag - 1);
		getTextAreaSentence().setText(problemData.getProblemCreationSentence());

		changeAnswerAndChoiceForm();

		if (problemData.answer != null) {
			for (int i = 0; i < problemData.answer.length; ++i) {
				final String answer = problemData.answer[i];
				if (answer == null) {
					continue;
				}

				textBoxAnswer[i].setText(answer);
			}
		}

		if (problemData.choice != null) {
			for (int i = 0; i < problemData.choice.length; ++i) {
				final String choice = problemData.choice[i];
				if (choice == null) {
					continue;
				}

				textBoxChoice[i].setText(choice);
			}
		}

		if (problemData.creator != null) {
			getTextBoxCreater().setText(problemData.creator);
		}

		getLabelAnswerCounter().setText(problemData.good + "/" + problemData.bad);
		labelVoteCounter.setText(problemData.voteGood + "/" + problemData.voteBad);

		textBoxNote.setText(problemData.note);
		checkBoxImageAnswer.setValue(problemData.imageAnswer);
		checkBoxImageChoice.setValue(problemData.imageChoice);

		problemId = -1;
		if (!copy) {
			problemId = problemData.problemId;
		}

		if (problemId == -1) {
			labelProblemNumber.setText("新規問題入力中");
			buttonRemovePlayerAnswers.setVisible(false);
		} else {
			labelProblemNumber.setText("問題番号" + problemId + "の問題を修正中");
			buttonRemovePlayerAnswers.setVisible(true);
		}

		// 問題評価文
		panelProblemFeedback.clear();
		if (problemId != -1) {
			Service.Util.getInstance().getProblemFeedback(problemId, callbackGetProblemFeedback);
		}
	}

	private final AsyncCallback<List<String>> callbackGetProblemFeedback = new AsyncCallback<List<String>>() {
		public void onSuccess(List<String> result) {
			for (String feedback : result) {
				panelProblemFeedback.add(new HTML(Sanitize.getInstance().html(feedback)));
			}

			if (!result.isEmpty()) {
				panelProblemFeedback.add(buttonClearProblemFeedback);
			}
		}

		public void onFailure(Throwable caught) {
		}
	};

	private void changeAnswerAndChoiceForm() {
		final int index = getListBoxType().getSelectedIndex();
		final String typeString = getListBoxType().getValue(index);
		final int type = Integer.parseInt(typeString);

		panelProblemCreation.setTypeCaution(TYPE_CAUTION[type]);

		for (int i = 0; i < 4; ++i) {
			textBoxAnswer[i].setEnabled(false);
			textBoxChoice[i].setEnabled(false);
			textBoxAnswer[i].setVisible(false);
			textBoxChoice[i].setVisible(false);
		}

		for (int i = 0; i < TYPE_INPUT_ANSWER[type]; ++i) {
			textBoxAnswer[i].setEnabled(true);
			textBoxAnswer[i].setVisible(true);
		}
		for (int i = TYPE_INPUT_ANSWER[type]; i < 4; ++i) {
			textBoxAnswer[i].setText("");
		}

		for (int i = 0; i < TYPE_INPUT_CHOICE[type]; ++i) {
			textBoxChoice[i].setEnabled(true);
			textBoxChoice[i].setVisible(true);
		}
		for (int i = TYPE_INPUT_CHOICE[type]; i < 4; ++i) {
			textBoxChoice[i].setText("");
		}

		checkBoxImageAnswer.setVisible(TYPE_IMAGE_ANSWER[type]);
		checkBoxImageChoice.setVisible(TYPE_IMAGE_CHOICE[type]);

		for (Button button : buttonPolygonCreation) {
			button.setVisible(TYPE_POLYGON_CREATION[type]);
		}
	}

	public void setEnable(boolean enabled) {
		for (int i = 0; i < 4; ++i) {
			textBoxAnswer[i].setEnabled(enabled);
			textBoxChoice[i].setEnabled(enabled);
		}
	}

	public PacketProblemData getProblemData() {
		final PacketProblemData problem = new PacketProblemData();

		// 問題番号
		problem.problemId = problemId;

		// ジャンル・出題形式
		problem.genre = Integer.parseInt(getListBoxGenre().getValue(getListBoxGenre().getSelectedIndex()));
		problem.type = Integer.parseInt(getListBoxType().getValue(getListBoxType().getSelectedIndex()));
		problem.randomFlag = listBoxRandomFlag.getSelectedIndex() + 1;

		// 問題文
		problem.setSentence(getTextAreaSentence().getText());

		boolean lastLetterOk = true;
		do {
			lastLetterOk = true;
			while (problem.sentence.endsWith("\n")) {
				problem.sentence = problem.sentence.substring(0, problem.sentence.length() - 1);
				lastLetterOk = false;
			}
			while (problem.sentence.endsWith("\r")) {
				problem.sentence = problem.sentence.substring(0, problem.sentence.length() - 1);
				lastLetterOk = false;
			}
		} while (!lastLetterOk);
		problem.sentence = problem.sentence.replaceAll("\r", "");
		problem.sentence = problem.sentence.replaceAll("\n", "%n");

		// 答え
		int index = 0;
		for (; index < 4 && textBoxAnswer[index].getText().length() != 0; ++index)
			;
		if (index != 0) {
			problem.answer = new String[index];
			for (int i = 0; i < index; ++i) {
				problem.answer[i] = textBoxAnswer[i].getText().replaceAll("&", "＆");

				if (problem.type == Constant.TYPE_TYPING || problem.type == Constant.TYPE_EFFECT || problem.type == Constant.TYPE_FLASH) {
					for (int letter = 0; letter < HALF_FULL_LETTER[0].length(); ++letter) {
						problem.answer[i] = problem.answer[i].replaceAll(HALF_FULL_LETTER[0].substring(letter, letter + 1), HALF_FULL_LETTER[1].substring(letter, letter + 1));
					}
				}
			}
		}

		// 選択肢
		index = 0;
		for (; index < 4 && textBoxChoice[index].getText().length() != 0; ++index)
			;
		if (index != 0) {
			problem.choice = new String[index];
			for (int i = 0; i < index; ++i) {
				problem.choice[i] = textBoxChoice[i].getText().replaceAll("&", "＆");
			}
		}

		switch (problem.type) {
		case Constant.TYPE_4TAKU:
		case Constant.TYPE_RENSOU: {
			problem.answer = new String[1];
			problem.answer[0] = problem.choice[0];
			break;
		}
		}

		// 作成者
		problem.creator = getTextBoxCreater().getText();

		// 回答数
		final String answerCount[] = getLabelAnswerCounter().getText().split("/");
		problem.good = Integer.parseInt(answerCount[0]);
		problem.bad = Integer.parseInt(answerCount[1]);

		// 投票数
		final String voteCount[] = labelVoteCounter.getText().split("/");
		problem.voteGood = Integer.parseInt(voteCount[0]);
		problem.voteBad = Integer.parseInt(voteCount[1]);

		// 問題ノート
		problem.note = textBoxNote.getText();

		problem.imageAnswer = isImageAnswer();
		problem.imageChoice = isImageChoice();

		final int[][] permutations = { Utility.getInstance().makePermutationArray(problem.getNumberOfAnswer()), Utility.getInstance().makePermutationArray(problem.getNumberOfChoice()) };
		problem.createRandomizedData(permutations);

		return problem;
	}

	private void resetAnswerCount() {
		getLabelAnswerCounter().setText("0/0");
	}

	private void resetVoteCount() {
		labelVoteCounter.setText("0/0");
	}

	private void removePlayerAnswer() {
		Service.Util.getInstance().removePlayerAnswers(problemId, Service.NULL_CALLBACK);
	}

	private void clearProblemFeedback() {
		if (problemId == -1) {
			return;
		}

		panelProblemFeedback.clear();
		Service.Util.getInstance().clearProblemFeedback(problemId, Service.NULL_CALLBACK);
	}

	public ListBox getListBoxGenre() {
		return listBoxGenre;
	}

	public ListBox getListBoxType() {
		return listBoxType;
	}

	public TextArea getTextAreaSentence() {
		return textAreaSentence;
	}

	public String getTextBoxAnswer(int index) {
		return textBoxAnswer[index].getText();
	}

	public String getTextBoxChoice(int index) {
		return textBoxChoice[index].getText();
	}

	public TextBox getTextBoxCreater() {
		return textBoxCreater;
	}

	public Label getLabelAnswerCounter() {
		return labelAnswerCounter;
	}

	public int getNumberOfChoice() {
		for (int i = 0; i < 4; ++i) {
			if (getTextBoxChoice(i).length() == 0) {
				return i;
			}
		}

		return 4;
	}

	public int getNumberOfAnswers() {
		for (int i = 0; i < 4; ++i) {
			if (getTextBoxAnswer(i).length() == 0) {
				return i;
			}
		}

		return 4;
	}

	public boolean isImageAnswer() {
		final int selectedIndex = getListBoxType().getSelectedIndex();
		final String value = getListBoxType().getValue(selectedIndex);
		final int type = Integer.parseInt(value);
		return TYPE_IMAGE_ANSWER[type] && checkBoxImageAnswer.getValue();
	}

	public boolean isImageChoice() {
		final int selectedIndex = getListBoxType().getSelectedIndex();
		final String value = getListBoxType().getValue(selectedIndex);
		final int type = Integer.parseInt(value);
		return TYPE_IMAGE_CHOICE[type] && checkBoxImageChoice.getValue();
	}

	public int getRandomFlag() {
		return listBoxRandomFlag.getSelectedIndex() + 1;
	}

	@Override
	public void onClick(ClickEvent event) {
		final Widget sender = (Widget) event.getSource();
		if (sender == buttonResetAnswerCount) {
			resetAnswerCount();
		} else if (sender == buttonResetVoteCount) {
			resetVoteCount();
		} else if (sender == buttonRemovePlayerAnswers) {
			removePlayerAnswer();
		} else if (buttonPolygonCreation.contains(sender)) {
			final int answerIndex = buttonPolygonCreation.indexOf(sender);
			final DialogBoxPolygonCreation polygonCreation = new DialogBoxPolygonCreation(getTextBoxChoice(0), getTextBoxAnswer(answerIndex));
			polygonCreation.addDialogBoxPolygonCreationListener(new DialogBoxPolygonCreationListener() {
				public void onOk() {
					textBoxAnswer[answerIndex].setText(polygonCreation.getPolygonDescription());
				}

				public void onCancel() {
				}
			});
			polygonCreation.show();
		} else if (sender == buttonClearProblemFeedback) {
			clearProblemFeedback();
		}
	}

	@Override
	public void onChange(ChangeEvent event) {
		final Widget sender = (Widget) event.getSource();
		if (sender == getListBoxType()) {
			changeAnswerAndChoiceForm();
		}
	}
}
